#include "Pch.h"

#include "../../MCD/Core/System/Path.h"

#include "../Fbx/FbxFile.h"
#include "../Fbx/TriangleBufferImporter.h"

#include "../Core/RayTrace/TriangleBufferIntersect.h"
#include "../Core/Application.h"

#include "GlVisualizer.h"

using namespace IS;

namespace TestTriangleBufferIntersect
{

class TestApp : public Application
{
public:
	LinkList<TriangleBuffer> mTriBufs;

	TestApp()
		: Application( L"title=TestTriangleBufferIntersect;width=800;height=600;FSAA=1" )
	{
		mCamera.moveForward(-10.0f);

		// open fbx file
		std::wstring fbxfilepath = (Path::getCurrentPath() / L"media/CornellBox.fbx").getString();

		Log::format( Log::Info, L"Importing %s ...", fbxfilepath.c_str() );

		FbxFile fbxfile(fbxfilepath.c_str());

		if(!fbxfile.open())
			return;

		Log::format( Log::Info, L"FBX file version %d.%d.%d"
			, fbxfile.fileVersion().major
			, fbxfile.fileVersion().minor
			, fbxfile.fileVersion().revision
			);

		// import triangle buffers
		TriangleBufferImporter().import(fbxfile, mTriBufs);
	}

	sal_override void update(float deltaTime)
	{
		// render the triangle buffers
		for(TriangleBuffer* tbuf = mTriBufs.begin(); tbuf != mTriBufs.end(); tbuf = tbuf->next())
		{
			glPushMatrix();
			glMultTransposeMatrixf(tbuf->localTransform.getPtr());

			tbuf->draw();

			glPopMatrix();
		}

		// some intersection test
		{
			TriangleBufferIntersect tbi;

			float ct = cosf(mAccumTime * 0.5f);

			Vec3f orig(0.0f, 10.0f + ct * 9.0f, 0.0f);
			Vec3f dir(1.0f, 0.0f, 0.0f);

			tbi.beginIntersect(mTriBufs);

			size_t hitCnt = tbi.intersect(orig, dir, true);

			glPushAttrib(GL_LIGHTING_BIT|GL_DEPTH_BUFFER_BIT);
			glDisable(GL_DEPTH_TEST);
			glDisable(GL_LIGHTING);

			glBegin(GL_LINES);

			const float s = 0.1f;

			for(size_t ihit = 0; ihit < hitCnt; ++ihit)
			{
				const TriangleBufferIntersect::Hit& hit = tbi.getHit(ihit);
                Vec3f hitPt = tbi.getHitPosition(ihit);
                Vec3f hitNrm = tbi.getHitNormal(ihit);

                MCD_VERIFY(hitPt.distance(orig + dir * hit.t) < 1e-5f);

				if(ihit == tbi.getClosestHitIndex())
					glColor3f(1.0f, 0.0f, 0.0f);
				else
					glColor3f(1.0f, 1.0f, 0.0f);

				GlVisualizer::drawPoint(hitPt, s);
                GlVisualizer::drawLine(orig, hitPt);

                glColor3f(0.0f, 0.0f, 1.0f);
                GlVisualizer::drawLine(hitPt, hitPt + hitNrm);
			}
			
			{
				glColor3f(0.0f, 1.0f, 0.0f);
				GlVisualizer::drawLine(orig, orig + dir * 2.0f);
				GlVisualizer::drawPoint(orig, s);
			}

			glEnd();

			glPopAttrib();

			tbi.endIntersect();
		}
		
	}

};	// class TestApp

}	// namespace TestTriangleBufferIntersect

TEST(TestTriangleBufferIntersect)
{
	TestTriangleBufferIntersect::TestApp app;
	app.mainLoop();
}